using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using FiltronASP.Areas.Admin.Consts;
using FiltronASP.Areas.Admin.ViewModels.Users;
using FiltronASP.Helpers.ActionFilters;
using FiltronASP.Helpers.Pagination;
using FiltronASP.Helpers.StringExtensions;
using FiltronASP.Models;
using FiltronASP.Models.DAO;
using FiltronASP.Models.DAO.Extensions;
using FiltronASP.Models.DAO.Interfaces;
using FiltronASP.Helpers.HashExtensions;
using System.Security.Cryptography;
using FiltronASP.Areas.Admin.ViewModels.Users.Helpers;
using FiltronASP.Areas.Admin.Helpers.Permissions;

namespace FiltronASP.Areas.Admin.Controllers
{
    public class UsersController : BaseController
    {

        protected IUserPageTypeDAO _userPageTypeDAO;

        protected IUserLanguageDAO _userLanguageDAO;

        /// <summary>
        /// Konstruktor.
        /// </summary>
        /// <param name="userDAO">klasa odpowiedzialna za operacja na bazie danych, tabela uzytkownikow</param>
        public UsersController(IUserDAO userDAO, IUserPageTypeDAO userPageTypeDAO,
            IUserLanguageDAO userLanguageDAO)
        {
            this._userDAO = userDAO;
            this._userLanguageDAO = userLanguageDAO;
            this._userPageTypeDAO = userPageTypeDAO;
        }

        /// <summary>
        /// Konstruktor (dependency injection).
        /// </summary>
        public UsersController()
            : this(new UserDAO(), new UserPageTypeDAO(), new UserLanguageDAO())
        {
        }

        /// <summary>
        /// Metoda pomocnicza do pobierania modelu <code>MenusIndexViewModel</code>.
        /// </summary>
        /// <param name="page">biezaca strona</param>
        /// <param name="menuId">aktualne menu</param>
        /// <param name="menuItemId">Aktualne nadrzedny element (folder)</param>
        /// <param name="currentLanguageId">biezacy jezyk</param>
        /// <returns>odpowiedni model danych</returns>
        private UsersIndexViewModel GetUsersIndexViewModel(int? page, int? currentLanguageId)
        {
            if (page == null)
            {
                return new UsersIndexViewModel(this.GetLanguagesToDropDown(currentLanguageId),
                        this.GetPageTypesInMenu(currentLanguageId),
                        this.GetMenus(currentLanguageId),
                        this.GetCurrentLanguage(currentLanguageId),
                        Pagination.ToPagedList<User>(this._userDAO.FindAll(), page ?? 1));
            }
            else
            {
                return new UsersIndexViewModel(this.GetLanguagesToDropDown(currentLanguageId),
                       this.GetPageTypesInMenu(currentLanguageId),
                       this.GetMenus(currentLanguageId),
                       this.GetCurrentLanguage(currentLanguageId),
                       Pagination.ToPagedList<User>(this._userDAO.FindAll(), page ?? 1),
                       page);
            }
        }

        /// <summary>
        /// Metoda pomocnicza do pobierania modelu <code>UsersEditionViewModel</code>.
        /// </summary>
        /// <param name="userToOperateWith">biezacy uzytkownik</param>
        /// <param name="paginationPage">strona w paginacji</param>
        /// <returns>odpowiedni model danych</returns>
        private UsersEditionViewModel GetUsersEditionViewModel(User userToOperateWith, int? paginationPage, int? currentLanguageId)
        {
            if (paginationPage == null)
            {
                paginationPage = 1;
            }   //if null
            if (userToOperateWith == null)
            {
                throw new Exception("UsersController exception: GetUsersEditionViewModel method, userToOperateWith object null...");
            }   //if null
            return new UsersEditionViewModel(this.GetLanguagesToDropDown(currentLanguageId),
                        this.GetPageTypesInMenu(currentLanguageId),
                        this.GetMenus(currentLanguageId),
                        this.GetCurrentLanguage(currentLanguageId),
                        userToOperateWith,
                        paginationPage.Value);
        }

        /// <summary>
        /// Metoda pomocnicza do pobierania modelu <code>UsersEditionViewModel</code>.
        /// </summary>
        /// <param name="userToOperateWith">biezacy uzytkownik</param>
        /// <param name="paginationPage">strona w paginacji</param>
        /// <returns>odpowiedni model danych</returns>
        private UsersEditionViewModel GetUsersEditionViewModel(User userToOperateWith, int? paginationPage, int? currentLanguageId, String login)
        {
            if (paginationPage == null)
            {
                paginationPage = 1;
            }   //if null
            if (userToOperateWith == null)
            {
                throw new Exception("UsersController exception: GetUsersEditionViewModel method, userToOperateWith object null...");
            }   //if null
            return new UsersEditionViewModel(this.GetLanguagesToDropDown(currentLanguageId),
                        this.GetPageTypesInMenu(currentLanguageId),
                        this.GetMenus(currentLanguageId),
                        this.GetCurrentLanguage(currentLanguageId),
                        userToOperateWith,
                        login,
                        paginationPage.Value);
        }

        /// <summary>
        /// Metoda pomocnicza do pobierania modelu <code>UserPermissionsEditionViewModel</code>.
        /// </summary>
        /// <param name="userToOperateWith">biezacy uzytkownik</param>
        /// <param name="paginationPage">strona w paginacji</param>
        /// <returns>odpowiedni model danych</returns>
        private UserPermissionsEditionViewModel GetUserPermissionsEditionViewModel(User userToOperateWith, int? paginationPage, int? currentLanguageId)
        {
            if (paginationPage == null)
            {
                paginationPage = 1;
            }   //if null
            if (userToOperateWith == null)
            {
                throw new Exception("UsersController exception: GetUserPermissionsEditionViewModel method, userToOperateWith object null...");
            }   //if null
            IQueryable<Language> availableLanguages = this._languageDAO.FindAll();
            return new UserPermissionsEditionViewModel(this.GetLanguagesToDropDown(currentLanguageId),
                        this.GetPageTypesInMenu(currentLanguageId),
                        this.GetMenus(currentLanguageId),
                        this.GetCurrentLanguage(currentLanguageId),
                        userToOperateWith,
                        availableLanguages,
                        this.GetAvailablePageTypes(availableLanguages),
                        paginationPage.Value);
        }

        /// <summary>
        /// Akcja dla wyswietlania uzytkownikow.
        /// </summary>
        /// <param name="currentPage">biezaca strona paginacji</param>
        /// <returns>widok</returns>
        [Authorize]
        public ActionResult Index(int? page, int? currentLanguageId)
        {
            if (!PermissionHelper.HasUserGlobalPermissionAccess(this.GetAuthenticatedUserId()))
            {
                return this.GetAccessDeniedView();
            }   //if
            try
            {
                if (page <= 0)
                {
                    page = 1;
                }   //if
                if ((page.HasValue) && (currentLanguageId.HasValue))
                {
                    return View(this.GetUsersIndexViewModel(page, currentLanguageId));
                }   //if all
                Language currentLanguage = null;
                if (!currentLanguageId.HasValue)
                {
                    currentLanguage = this._languageDAO.GetDefaultLanguage(this.GetAuthenticatedUserId());
                    if (currentLanguage != null)
                    {
                        currentLanguageId = currentLanguage.language_id;
                    }   //if
                }
                else
                {   //if lang id null
                    currentLanguage = this._languageDAO.FindByPK(currentLanguageId);
                }   //else lang id null
                return View(this.GetUsersIndexViewModel(page, currentLanguageId));
            }   //try
            catch (Exception ex)
            {
                Logger.MyLogger.Log(ex);
                return View("Errors/UsersError", this.GetBaseViewModel(currentLanguageId));
            }   //catch
        }

        /// <summary>
        /// Tworzenie nowego uzytkownika.
        /// </summary>
        /// <param name="viewModel">model danych</param>
        /// <returns>widok</returns>
        [AcceptVerbs(HttpVerbs.Post)]
        [Authorize]
        public ActionResult Create(UsersIndexViewModel viewModel)
        {
            if (!PermissionHelper.HasUserGlobalPermissionAccess(this.GetAuthenticatedUserId()))
            {
                return this.GetAccessDeniedView();
            }   //if
            if (viewModel == null)
            {
                Logger.MyLogger.Log("UsersController exception: Create method, viewModel object null...");
                return View("Errors/UsersError", this.GetBaseViewModel(null));
            }   //if null
            if (viewModel.CurrentLanguage != null)
            {
                return View(this.GetUsersEditionViewModel(new User(), viewModel.PaginationPage,
                    viewModel.CurrentLanguage.language_id));
            }   //if
            Language currentLanguage = this._languageDAO.GetDefaultLanguage(this.GetAuthenticatedUserId());
            if (currentLanguage != null)
            {
                return View(this.GetUsersEditionViewModel(new User(), viewModel.PaginationPage,
                    currentLanguage.language_id));
            }   //if
            return View(this.GetUsersEditionViewModel(new User(), viewModel.PaginationPage,
                null));
        }

        /// <summary>
        /// Akcja do zapisu nowego uzytkownika.
        /// </summary>
        /// <param name="viewModel">model danych</param>
        /// <param name="collection">parametry z forma</param>
        /// <returns>widok</returns>
        [AcceptVerbs(HttpVerbs.Post)]
        [ValidateOnlyIncomingValues]
        [ValidateInput(false)]
        [Authorize]
        public ActionResult CreateNewUser(UsersEditionViewModel viewModel, FormCollection formParams)
        {
            if (!PermissionHelper.HasUserGlobalPermissionAccess(this.GetAuthenticatedUserId()))
            {
                return this.GetAccessDeniedView();
            }   //if
            if (viewModel == null)
            {
                Logger.MyLogger.Log("UsersController exception: CreateNewUser method, viewModel object null...");
                return View("Errors/UsersError", this.GetBaseViewModel(null));
            }   //if null
            if (viewModel.UserToOperateWith == null)
            {
                Logger.MyLogger.Log("UsersController exception: CreateNewUser method, UserToOperateWith object null...");
                if (viewModel.CurrentLanguage != null)
                {
                    return View("Errors/UsersErrorNoMenuItemFound", this.GetBaseViewModel(null));
                }   //if
                return View("Errors/UsersErrorNoMenuItemFound", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
            }   //if null
            try
            {
                if (!IsLoginAvailable(viewModel.UserToOperateWith.user_login))
                {
                    ModelState.AddModelError("UserToOperateWith.user_login", "Wybrany login jest już zajęty.");
                    if (viewModel.CurrentLanguage != null)
                    {
                        return View("Create", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                            viewModel.PaginationPage,
                            viewModel.CurrentLanguage.language_id));
                    }   //if
                    return View("Create", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                        viewModel.PaginationPage,
                        null));
                }
                if (viewModel.password == null || viewModel.confirmPassword == null)
                {
                    ModelState.AddModelError("password", "Hasło nie może być krótsze niż 5 znaków.");
                    if (viewModel.CurrentLanguage != null)
                    {
                        return View("Create", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                            viewModel.PaginationPage,
                            viewModel.CurrentLanguage.language_id));
                    }   //if
                    return View("Create", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                        viewModel.PaginationPage,
                        null));
                }
                if (viewModel.password.Length < 5)
                {
                    ModelState.AddModelError("password", "Hasło nie może być krótsze niż 5 znaków.");
                    if (viewModel.CurrentLanguage != null)
                    {
                        return View("Create", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                            viewModel.PaginationPage,
                            viewModel.CurrentLanguage.language_id));
                    }   //if
                    return View("Create", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                        viewModel.PaginationPage,
                        null));
                }
                if (viewModel.password.ToString() != viewModel.confirmPassword.ToString())
                {
                    ModelState.AddModelError("password", "Podane hasła muszą być takie same.");
                    if (viewModel.CurrentLanguage != null)
                    {
                        return View("Create", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                            viewModel.PaginationPage,
                            viewModel.CurrentLanguage.language_id));
                    }   //if
                    return View("Create", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                        viewModel.PaginationPage, null));
                }
                if (ModelState.IsValid)
                {
                    if (InsertNewUser(viewModel.UserToOperateWith, viewModel.password) == null)
                    {
                        if (viewModel.CurrentLanguage == null)
                        {
                            return View("Errors/UsersError", this.GetBaseViewModel(null));
                        }   //if
                        return View("Errors/UsersError", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
                    }   //if
                    if (viewModel.CurrentLanguage != null)
                    {
                        return View("Index", this.GetUsersIndexViewModel(viewModel.PaginationPage,
                            viewModel.CurrentLanguage.language_id));
                    }   //if
                    Language currentLanguage = this._languageDAO.GetDefaultLanguage(this.GetAuthenticatedUserId());
                    if (currentLanguage != null)
                    {
                        return View("Index", this.GetUsersIndexViewModel(viewModel.PaginationPage,
                            currentLanguage.language_id));
                    }   //if
                    return View("Index", this.GetUsersIndexViewModel(viewModel.PaginationPage,
                        null));
                }   //if valid
                if (viewModel.CurrentLanguage != null)
                {
                    return View("Create", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                        viewModel.PaginationPage,
                        viewModel.CurrentLanguage.language_id));
                } //if
                return View("Create", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                    viewModel.PaginationPage,
                    null));
            }   //try
            catch (Exception ex)
            {
                Logger.MyLogger.Log(ex);
                if (viewModel.CurrentLanguage != null)
                {
                    return View("Errors/UsersError", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
                }   //if
                return View("Errors/UsersError", this.GetBaseViewModel(null));
            }   //catch
        }

        /// <summary>
        /// Sprawdzanie czy dany login juz istnieje
        /// </summary>
        /// <param name="login">login</param>
        /// <returns>true jesli login jest dostepny, false wpp</returns>
        private bool IsLoginAvailable(String login)
        {
            if (_userDAO.FindByUserLogin(login) == null)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Tworzenie nowego uzytkownika
        /// </summary>
        /// <param name="user">uzytkownik</param>
        /// <returns>nowy uzytkownik lub null</returns>
        private User InsertNewUser(User user, string password)
        {
            try
            {
                if (user == null)
                {
                    Logger.MyLogger.Log("UsersController exception: InsertNewUser method, user null...");
                    return null;
                }   //if
                User newUser = new User();
                newUser.user_created = DateTime.Now;
                newUser.user_modified = DateTime.Now;
                newUser.user_login = user.user_login;
                newUser.user_first_name = user.user_first_name;
                newUser.user_last_name = user.user_last_name;
                newUser.user_mail_address = user.user_mail_address;
                newUser.user_permission_access = false;
                string guidResult = System.Guid.NewGuid().ToString();
                guidResult = guidResult.Substring(0, 6);
                newUser.user_pass_salt = guidResult;
                newUser.user_pass_hash = SHA1.Create().ComputeHash(password + newUser.user_pass_salt).ToBase64();
                return this._userDAO.Add(newUser);
            }   //try
            catch (Exception ex)
            {
                Logger.MyLogger.Log(ex);
                return null;
            }   //catch            
        }

        /// <summary>
        /// Usuwanie uzytkownika.
        /// </summary>
        /// <param name="viewModel">model danych</param>
        /// <returns>widok</returns>
        [AcceptVerbs(HttpVerbs.Post)]
        [Authorize]
        public ActionResult DeleteUser(UsersEditionViewModel viewModel)
        {
            if (!PermissionHelper.HasUserGlobalPermissionAccess(this.GetAuthenticatedUserId()))
            {
                return this.GetAccessDeniedView();
            }   //if
            if (viewModel == null)
            {
                Logger.MyLogger.Log("UsersController exception: DeleteUser method, viewModel object null...");
                return View("Errors/UsersError", this.GetBaseViewModel(null));
            }   //if null
            if (viewModel.UserToOperateWith == null)
            {
                Logger.MyLogger.Log("UsersController exception: DeleteUser method, new user object null...");
                if (viewModel.CurrentLanguage != null)
                {
                    return View("Errors/UsersError", this.GetBaseViewModel(null));
                }   //if
                return View("Errors/UsersError", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
            }   //if null
            if (viewModel.CurrentLanguage != null)
            {
                return View(this.GetUsersEditionViewModel(viewModel.UserToOperateWith, viewModel.PaginationPage,
                    viewModel.CurrentLanguage.language_id));
            } //if
            Language currentLanguage = this._languageDAO.GetDefaultLanguage(this.GetAuthenticatedUserId());
            if (currentLanguage != null)
            {
                return View(this.GetUsersEditionViewModel(viewModel.UserToOperateWith, viewModel.PaginationPage,
                    currentLanguage.language_id));
            }   //if
            return View(this.GetUsersEditionViewModel(viewModel.UserToOperateWith, viewModel.PaginationPage,
                null));
        }

        /// <summary>
        /// Usuwanie uzytkownika.
        /// </summary>
        /// <param name="userToDeleteId">id uzytkownika do skasowania</param>
        /// <param name="page">strona</param>
        /// <param name="currentLanguageId">id jezyka</param>
        /// <returns>widok</returns>
        [AcceptVerbs(HttpVerbs.Get)]
        [Authorize]
        public ActionResult Delete(int userToDeleteId, int? page, int? currentLanguageId)
        {
            if (!PermissionHelper.HasUserGlobalPermissionAccess(this.GetAuthenticatedUserId()))
            {
                return this.GetAccessDeniedView();
            }   //if
            try
            {
                User userToDelete = _userDAO.FindByPK(userToDeleteId);
                if (userToDelete != null)
                {
                    return View("DeleteUser", this.GetUsersEditionViewModel(userToDelete, page,
                                currentLanguageId));
                }
                Logger.MyLogger.Log("UsersController exception: Delete method, user null...");
                return View("Errors/UsersError", this.GetBaseViewModel(null));
            }   //catch
            catch (Exception ex)
            {
                Logger.MyLogger.Log(ex);
                return View("Errors/UsersError", this.GetBaseViewModel(currentLanguageId));
            }   //catch
        }

        /// <summary>
        /// Usuwanie uzytkownika.
        /// </summary>
        /// <param name="viewModel">model danych</param>
        /// <returns>widok</returns>
        [AcceptVerbs(HttpVerbs.Post)]
        [Authorize]
        public ActionResult DeleteConfirmed(UsersEditionViewModel viewModel)
        {
            if (!PermissionHelper.HasUserGlobalPermissionAccess(this.GetAuthenticatedUserId()))
            {
                return this.GetAccessDeniedView();
            }   //if
            if (viewModel.UserToOperateWith == null)
            {
                Logger.MyLogger.Log("UsersController exception: DeleteUser method, UserToOperateWith null...");
                return View("Errors/UsersError", this.GetBaseViewModel(null));
            }   //if null
            try
            {
                if (viewModel.UserToOperateWith.user_id != 1)
                {
                    if (this._userDAO.Delete(viewModel.UserToOperateWith.user_id))
                    {
                        if (this._userDAO.SubmitChanges())
                        {
                            if (viewModel.CurrentLanguage != null)
                            {
                                return View("Index", this.GetUsersIndexViewModel(viewModel.PaginationPage,
                                    viewModel.CurrentLanguage.language_id));
                            } //if
                            Language currentLanguage = this._languageDAO.GetDefaultLanguage(this.GetAuthenticatedUserId());
                            if (currentLanguage != null)
                            {
                                return View("Index", this.GetUsersIndexViewModel(viewModel.PaginationPage,
                                    currentLanguage.language_id));
                            }   //if
                            return View("Index", this.GetUsersIndexViewModel(viewModel.PaginationPage,
                                null));
                        }   //if submit
                    }   //if
                }
                Logger.MyLogger.Log("UsersController exception: DeleteUser method, unable to delete user...");
                if (viewModel.CurrentLanguage == null)
                {
                    return View("Errors/UsersError", this.GetBaseViewModel(null));
                }   //if
                return View("Errors/UsersError", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
            }   //catch
            catch (Exception ex)
            {
                Logger.MyLogger.Log(ex);
                if (viewModel.CurrentLanguage == null)
                {
                    return View("Errors/UsersError", this.GetBaseViewModel(null));
                }   //if
                return View("Errors/UsersError", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
            }   //catch
        }

        /// <summary>
        /// Edycja uzytkownika.
        /// </summary>
        /// <param name="viewModel">model danych</param>
        /// <returns>widok</returns>
        [AcceptVerbs(HttpVerbs.Post)]
        [Authorize]
        public ActionResult EditUser(UsersEditionViewModel viewModel)
        {
            if (!PermissionHelper.HasUserGlobalPermissionAccess(this.GetAuthenticatedUserId()))
            {
                return this.GetAccessDeniedView();
            }   //if
            if (viewModel == null)
            {
                Logger.MyLogger.Log("UsersController exception: EditUser method, viewModel object null...");
                return View("Errors/UsersError", this.GetBaseViewModel(null));
            }   //if null
            if (viewModel.UserToOperateWith == null)
            {
                Logger.MyLogger.Log("UsersController exception: EditUser method, viewModel.UserToOperateWith object null...");
                if (viewModel.CurrentLanguage == null)
                {
                    return View("Errors/UsersError", this.GetBaseViewModel(null));
                }   //if
                return View("Errors/UsersError", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
            }   //if null
            if (viewModel.CurrentLanguage != null)
            {
                return View(this.GetUsersEditionViewModel(viewModel.UserToOperateWith, viewModel.PaginationPage,
                    viewModel.CurrentLanguage.language_id));
            } //if
            Language currentLanguage = this._languageDAO.GetDefaultLanguage(this.GetAuthenticatedUserId());
            if (currentLanguage != null)
            {
                return View(this.GetUsersEditionViewModel(viewModel.UserToOperateWith, viewModel.PaginationPage,
                    currentLanguage.language_id));
            }   //if
            return View(this.GetUsersEditionViewModel(viewModel.UserToOperateWith, viewModel.PaginationPage,
                null));
        }

        /// <summary>
        /// Edycja uzytkownika.
        /// </summary>
        /// <param name="userToEditId">id uzytkownika do edycji</param>
        /// <param name="page">strona</param>
        /// <param name="currentLanguageId">id jezyka</param>
        /// <returns>widok</returns>
        [AcceptVerbs(HttpVerbs.Get)]
        [Authorize]
        public ActionResult Edit(int userToEditId, int? page, int? currentLanguageId, String login)
        {
            if (!PermissionHelper.HasUserGlobalPermissionAccess(this.GetAuthenticatedUserId()))
            {
                return this.GetAccessDeniedView();
            }   //if
            if (login == null)
            {
                Logger.MyLogger.Log("UsersController exception: Edit method, login null...");
                return View("Errors/UsersError", this.GetBaseViewModel(null));
            }   //if null
            try
            {
                User userToEdit = _userDAO.FindByPK(userToEditId);
                if (userToEdit != null)
                {
                    return View("EditUser", this.GetUsersEditionViewModel(userToEdit, page,
                                currentLanguageId, login));
                }
                Logger.MyLogger.Log("UsersController exception: Edit method, user null...");
                return View("Errors/UsersError", this.GetBaseViewModel(null));
            }   //catch
            catch (Exception ex)
            {
                Logger.MyLogger.Log(ex);
                return View("Errors/UsersError", this.GetBaseViewModel(currentLanguageId));
            }   //catch
        }

        /// <summary>
        /// Metoda do aktualizacji danych uzytkownika w bazie na podstawie zadania.
        /// </summary>
        /// <param name="viewModel">model danych</param>
        /// <returns>true, gdy sie uda, false wpp</returns>
        [AcceptVerbs(HttpVerbs.Post)]
        [ValidateOnlyIncomingValues]
        [ValidateInput(false)]
        [Authorize]
        public ActionResult UpdateUser(UsersEditionViewModel viewModel, FormCollection formParams)
        {
            if (!PermissionHelper.HasUserGlobalPermissionAccess(this.GetAuthenticatedUserId()))
            {
                return this.GetAccessDeniedView();
            }   //if
            if (viewModel == null)
            {
                Logger.MyLogger.Log("UsersController exception: UpdateUser method, viewModel object null...");
                return View("Errors/UsersError", this.GetBaseViewModel(null));
            }   //if null
            if (viewModel.UserToOperateWith == null)
            {
                Logger.MyLogger.Log("UsersController exception: UpdateUser method, UserToOperateWith object null...");
                if (viewModel.CurrentLanguage == null)
                {
                    return View("Errors/UsersErrorNoMenuItemFound", this.GetBaseViewModel(null));
                }   //if
                return View("Errors/UsersErrorNoMenuItemFound", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
            }   //if null
            try
            {
                if (!IsLoginAvailable(viewModel.UserToOperateWith.user_login) && (viewModel.login == viewModel.UserToOperateWith.user_login))
                {
                    ModelState.AddModelError("UserToOperateWith.user_first_name", "Wzbranz login jest już zajęty.");
                    if (viewModel.CurrentLanguage != null)
                    {
                        return View("EditUser", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                            viewModel.PaginationPage,
                            viewModel.CurrentLanguage.language_id,
                            viewModel.login));
                    }   //if
                    return View("EditUser", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                            viewModel.PaginationPage,
                            null,
                            viewModel.login));
                }
                if (ModelState.IsValid)
                {
                    User userToUpdate = this._userDAO.FindByPK(viewModel.UserToOperateWith.user_id);
                    if (userToUpdate == null)
                    {
                        Logger.MyLogger.Log("UsersController exception: UpdateUser method, unable to find user to update...");
                        if (viewModel.CurrentLanguage == null)
                        {
                            return View("Errors/UsersError", this.GetBaseViewModel(null));
                        }   //if
                        return View("Errors/UsersError", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
                    }   //if null
                    userToUpdate.user_login = viewModel.UserToOperateWith.user_login;
                    userToUpdate.user_first_name = viewModel.UserToOperateWith.user_first_name;
                    userToUpdate.user_last_name = viewModel.UserToOperateWith.user_last_name;
                    userToUpdate.user_mail_address = viewModel.UserToOperateWith.user_mail_address;
                    if (!this._userDAO.SubmitChanges())
                    {
                        if (viewModel.CurrentLanguage == null)
                        {
                            return View("Errors/UsersError", this.GetBaseViewModel(null));
                        }   //if
                        return View("Errors/UsersError", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
                    }   //if
                    if (viewModel.CurrentLanguage != null)
                    {
                        return View("Index", this.GetUsersIndexViewModel(viewModel.PaginationPage,
                            viewModel.CurrentLanguage.language_id));
                    } //if
                    Language currentLanguage = this._languageDAO.GetDefaultLanguage(this.GetAuthenticatedUserId());
                    if (currentLanguage != null)
                    {
                        return View("Index", this.GetUsersIndexViewModel(viewModel.PaginationPage,
                            currentLanguage.language_id));
                    }   //if
                    return View("Index", this.GetUsersIndexViewModel(viewModel.PaginationPage,
                        null));
                }   //if valid
                if (viewModel.CurrentLanguage != null)
                {
                    return View("EditUser", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                            viewModel.PaginationPage,
                            viewModel.CurrentLanguage.language_id,
                            viewModel.login));
                } //if
                return View("EditUser", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                        viewModel.PaginationPage,
                        null,
                        viewModel.login));
            }   //try
            catch (Exception ex)
            {
                Logger.MyLogger.Log(ex);
                if (viewModel.CurrentLanguage != null)
                {
                    return View("Errors/UsersError", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
                }   //if
                return View("Errors/UsersError", this.GetBaseViewModel(null));
            }   //catch
        }

        /// <summary>
        /// Metoda do aktualizacji danych uzytkownika w bazie na podstawie zadania.
        /// </summary>
        /// <param name="viewModel">model danych</param>
        /// <returns>true, gdy sie uda, false wpp</returns>
        [AcceptVerbs(HttpVerbs.Post)]
        [ValidateOnlyIncomingValues]
        [ValidateInput(false)]
        [Authorize]
        public ActionResult UpdateUserPassword(UsersEditionViewModel viewModel, FormCollection formParams)
        {
            if (!PermissionHelper.HasUserGlobalPermissionAccess(this.GetAuthenticatedUserId()))
            {
                return this.GetAccessDeniedView();
            }   //if
            if (viewModel == null)
            {
                Logger.MyLogger.Log("UsersController exception: UpdateUser method, viewModel object null...");
                return View("Errors/UsersError", this.GetBaseViewModel(null));
            }   //if null
            if (viewModel.UserToOperateWith == null)
            {
                Logger.MyLogger.Log("UsersController exception: UpdateUser method, UserToOperateWith object null...");
                if (viewModel.CurrentLanguage == null)
                {
                    return View("Errors/UsersError", this.GetBaseViewModel(null));
                }   //if
                return View("Errors/UsersError", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
            }   //if null
            try
            {
                viewModel.UserToOperateWith = this._userDAO.FindByPK(viewModel.UserToOperateWith.user_id);
                if (viewModel.UserToOperateWith == null)
                {
                    Logger.MyLogger.Log("UsersController exception: UpdateUser method, UserToOperateWith object null...");
                    if (viewModel.CurrentLanguage == null)
                    {
                        return View("Errors/UsersErrorNoMenuItemFound", this.GetBaseViewModel(null));
                    }   //if
                    return View("Errors/UsersErrorNoMenuItemFound", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
                }   //if null
                if (viewModel.password == null || viewModel.confirmPassword == null)
                {
                    ModelState.AddModelError("password", "Hasło nie może być krótsze niż 5 znaków.");
                    if (viewModel.CurrentLanguage != null)
                    {
                        return View("EditUser", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                            viewModel.PaginationPage,
                            viewModel.CurrentLanguage.language_id,
                            viewModel.login));
                    }   //if
                    return View("EditUser", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                        viewModel.PaginationPage,
                        null,
                        viewModel.login));
                }
                if (viewModel.password.Length < 5)
                {
                    ModelState.AddModelError("password", "Hasło nie może być krótsze niż 5 znaków.");
                    if (viewModel.CurrentLanguage != null)
                    {
                        return View("EditUser", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                            viewModel.PaginationPage,
                            viewModel.CurrentLanguage.language_id,
                            viewModel.login));
                    }   //if
                    return View("EditUser", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                        viewModel.PaginationPage,
                        null,
                        viewModel.login));
                }
                if (viewModel.password.ToString() != viewModel.confirmPassword.ToString())
                {
                    ModelState.AddModelError("password", "Hasło i jego potwierdzenie nie odpowiadają sobie.");
                    if (viewModel.CurrentLanguage != null)
                    {
                        return View("EditUser", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                            viewModel.PaginationPage,
                            viewModel.CurrentLanguage.language_id,
                            viewModel.login));
                    } //if
                    return View("EditUser", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                        viewModel.PaginationPage,
                        null,
                        viewModel.login));
                }
                if (ModelState.IsValid)
                {
                    User userToUpdate = this._userDAO.FindByPK(viewModel.UserToOperateWith.user_id);
                    if (userToUpdate == null)
                    {
                        Logger.MyLogger.Log("UsersController exception: UpdateUser method, unable to find user to update...");
                        if (viewModel.CurrentLanguage == null)
                        {
                            return View("Errors/UsersError", this.GetBaseViewModel(null));
                        }   //if
                        return View("Errors/UsersError", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
                    }   //if null
                    userToUpdate.user_pass_hash = SHA1.Create().ComputeHash(viewModel.password + userToUpdate.user_pass_salt).ToBase64();
                    if (!this._userDAO.SubmitChanges())
                    {
                        if (viewModel.CurrentLanguage == null)
                        {
                            return View("Errors/UsersError", this.GetBaseViewModel(null));
                        }   //if
                        return View("Errors/UsersError", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
                    }   //if
                    if (viewModel.CurrentLanguage != null)
                    {
                        return View("Index", this.GetUsersIndexViewModel(viewModel.PaginationPage,
                            viewModel.CurrentLanguage.language_id));
                    } //if
                    Language currentLanguage = this._languageDAO.GetDefaultLanguage(this.GetAuthenticatedUserId());
                    if (currentLanguage != null)
                    {
                        return View("Index", this.GetUsersIndexViewModel(viewModel.PaginationPage,
                            currentLanguage.language_id));
                    }   //if
                    return View("Index", this.GetUsersIndexViewModel(viewModel.PaginationPage,
                        null));
                }   //if valid
                if (viewModel.CurrentLanguage != null)
                {
                    return View("EditUser", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                            viewModel.PaginationPage,
                            viewModel.CurrentLanguage.language_id,
                            viewModel.login));
                } //if
                return View("EditUser", this.GetUsersEditionViewModel(viewModel.UserToOperateWith,
                        viewModel.PaginationPage,
                        null,
                        viewModel.login));
            }   //try
            catch (Exception ex)
            {
                Logger.MyLogger.Log(ex);
                if (viewModel.CurrentLanguage != null)
                {
                    return View("Errors/UsersError", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
                }   //if
                return View("Errors/UsersError", this.GetBaseViewModel(null));
            }   //catch
        }

        /// <summary>
        /// Edycja uprawnien uzytkownika.
        /// </summary>
        /// <param name="viewModel">model danych</param>
        /// <returns>widok</returns>
        [AcceptVerbs(HttpVerbs.Get)]
        [Authorize]
        public ActionResult EditUserPermissions(int userToEditId, int? page, int? currentLanguageId)
        {
            if (!PermissionHelper.HasUserGlobalPermissionAccess(this.GetAuthenticatedUserId()))
            {
                return this.GetAccessDeniedView();
            }   //if
            try
            {
                User userToEdit = _userDAO.FindByPK(userToEditId);
                if (userToEdit != null)
                {
                    return View(this.GetUserPermissionsEditionViewModel(userToEdit, page,
                                currentLanguageId));
                }
                Logger.MyLogger.Log("UsersController exception: EditUserPermissions method, user null...");
                return View("Errors/UsersError", this.GetBaseViewModel(null));
            }   //catch
            catch (Exception ex)
            {
                Logger.MyLogger.Log(ex);
                return View("Errors/UsersError", this.GetBaseViewModel(currentLanguageId));
            }   //catch
        }

        /// <summary>
        /// Edycja uprawnien uzytkownika.
        /// </summary>
        /// <param name="viewModel">model danych</param>
        /// <returns>widok</returns>
        [AcceptVerbs(HttpVerbs.Post)]
        [ValidateOnlyIncomingValues]
        [ValidateInput(false)]
        [Authorize]
        public ActionResult SubmitUserPermissions(UserPermissionsEditionViewModel viewModel, FormCollection formParams)
        {
            if (!PermissionHelper.HasUserGlobalPermissionAccess(this.GetAuthenticatedUserId()))
            {
                return this.GetAccessDeniedView();
            }   //if
            if (viewModel == null)
            {
                Logger.MyLogger.Log("UsersController exception: SubmitUserPermissions method, viewModel object null...");
                return View("Errors/UsersError", this.GetBaseViewModel(null));
            }   //if null
            if (viewModel.UserToOperateWith == null)
            {
                Logger.MyLogger.Log("UsersController exception: SubmitUserPermissions method, viewModel.UserToOperateWith object null...");
                if (viewModel.CurrentLanguage == null)
                {
                    return View("Errors/UsersError", this.GetBaseViewModel(null));
                }   //if
                return View("Errors/UsersError", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
            }
            if (!this.UpdateUserLanguages(viewModel.UserToOperateWith, formParams))
            {
                if (viewModel.CurrentLanguage == null)
                {
                    return View("Errors/UsersError", this.GetBaseViewModel(null));
                }   //if
                return View("Errors/UsersError", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
            }   //if
            if (viewModel.CurrentLanguage != null)
            {
                if (!this.IsCurrentLanguageAvailable(this.GetAuthenticatedUserId(), viewModel.CurrentLanguage))
                {
                    viewModel.CurrentLanguage = this._languageDAO.GetDefaultLanguage(this.GetAuthenticatedUserId());
                }   //if
            }   //if
            if (!this.UpdateUserPageTypes(viewModel.UserToOperateWith, formParams))
            {
                if (viewModel.CurrentLanguage == null)
                {
                    return View("Errors/UsersError", this.GetBaseViewModel(null));
                }   //if
                return View("Errors/UsersError", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
            }   //if
            if (!this.UpdateUserGlobalPermissions(viewModel.UserToOperateWith, formParams))
            {
                if (viewModel.CurrentLanguage == null)
                {
                    return View("Errors/UsersError", this.GetBaseViewModel(null));
                }   //if
                return View("Errors/UsersError", this.GetBaseViewModel(viewModel.CurrentLanguage.language_id));
            }   //if
            if (viewModel.CurrentLanguage != null)
            {
                return View("Index", this.GetUsersIndexViewModel(viewModel.PaginationPage, viewModel.CurrentLanguage.language_id));
            }   //if
            Language currentLanguage = this._languageDAO.GetDefaultLanguage(this.GetAuthenticatedUserId());
            if (currentLanguage != null)
            {
                return View("Index", this.GetUsersIndexViewModel(viewModel.PaginationPage, currentLanguage.language_id));
            }   //if
            return View("Index", this.GetUsersIndexViewModel(viewModel.PaginationPage, null));
        }

        private List<LanguagePageTypes> GetAvailablePageTypes(IQueryable<Language> languages)
        {
            try
            {
                if (languages == null)
                {
                    return null;
                }   //if
                if (!languages.Any())
                {
                    return null;
                }   //if
                List<LanguagePageTypes> availablePageTypes = new List<LanguagePageTypes>();
                foreach (Language language in languages)
                {
                    IQueryable<PageType> pageTypes = this._pageTypeDAO.FindByLanguage(language.language_id);
                    if (pageTypes != null)
                    {
                        LanguagePageTypes languagePageTypes = new LanguagePageTypes(pageTypes, language.language_abbr);
                        availablePageTypes.Add(languagePageTypes);
                    }   //if
                }   //if
                return availablePageTypes;
            }
            catch (Exception ex)
            {
                Logger.MyLogger.Log(ex);
                return null;
            }   //catch
        }

        /// <summary>
        /// Usuwanie wskazanych wersji jezykowych dla uzytkownika.
        /// </summary>
        /// <returns>widok</returns>        
        /// <param name="viewModel">model danych</param>
        private bool DeleteUserLanguages(User user)
        {
            if (user == null)
            {
                Logger.MyLogger.Log("UsersController exception: DeleteUserLanguages method, user object null...");
                return false;
            }   //if null
            if (this._userLanguageDAO.FindByUserId(user.user_id) == null)
            {
                return true;
            }   //if
            return this._userLanguageDAO.DeleteByUserId(user.user_id);
        }

        /// <summary>
        /// Usuwanie wskazanych grup stron dla uzytkownika.
        /// </summary>
        /// <returns>widok</returns>        
        /// <param name="viewModel">model danych</param>
        private bool DeleteUserPageTypes(User user)
        {
            if (user == null)
            {
                Logger.MyLogger.Log("UsersController exception: DeleteUserPageTypes method, user object null...");
                return false;
            }   //if null
            if (this._userPageTypeDAO.FindByUserId(user.user_id) == null)
            {
                return true;
            }   //if
            return this._userPageTypeDAO.DeleteByUserId(user.user_id);
        }

        /// <summary>
        /// Akcja do aktualizowania wersji jezykowych dostepnych dla uzytkownika.
        /// </summary>
        /// <returns>widok</returns>        
        /// <param name="viewModel">model danych</param>
        /// <param name="collection">parametry z forma</param>
        private bool UpdateUserLanguages(User user, FormCollection formParams)
        {
            try
            {
                if (user == null)
                {
                    Logger.MyLogger.Log("UsersController exception: UpdateUserLanguages method, user null...");
                    return false;
                }   //if null
                if (!this.DeleteUserLanguages(user))
                {
                    Logger.MyLogger.Log("UsersController exception: UpdateUserLanguages method, unable to delete user languages...");
                    return false;
                }   //if
                if (formParams == null)
                {
                    Logger.MyLogger.Log("UsersController exception: UpdateUserLanguages method, form params null object...");
                    return false;
                }   //if
                String acceptableLanguages = formParams.Get(UsersConsts.USER_LANGUAGES_REQUEST_PARAM);
                if (String.IsNullOrEmpty(acceptableLanguages))
                {
                    return true;
                }   //if
                String[] acceptableLanguageIds = acceptableLanguages.Split(',');
                if (acceptableLanguageIds == null)
                {
                    return true;
                }   //if
                foreach (string acceptableLanguageId in acceptableLanguageIds)
                {
                    UserLanguage userLanguage = new UserLanguage();
                    userLanguage.language_id = Int32.Parse(acceptableLanguageId);
                    userLanguage.user_id = user.user_id;
                    userLanguage.user_language_created = DateTime.Now;
                    userLanguage.user_language_modified = DateTime.Now;
                    if (this._userLanguageDAO.Add(userLanguage) == null)
                    {
                        Logger.MyLogger.Log("UsersController exception: UpdateUserLanguages method, unable to add user language to database...");
                        return false;
                    }   //if null
                }   //foreach
                return true;
            }
            catch (Exception ex)
            {
                Logger.MyLogger.Log(ex);
                return false;
            }   //catch            
        }

        /// <summary>
        /// Akcja do aktualizowania grup stron dostepnych dla uzytkownika.
        /// </summary>
        /// <returns>widok</returns>        
        /// <param name="viewModel">model danych</param>
        /// <param name="collection">parametry z forma</param>
        private bool UpdateUserPageTypes(User user, FormCollection formParams)
        {
            try
            {
                if (user == null)
                {
                    Logger.MyLogger.Log("UsersController exception: UpdateUserPageTypes method, user null...");
                    return false;
                }   //if null
                if (!this.DeleteUserPageTypes(user))
                {
                    Logger.MyLogger.Log("UsersController exception: UpdateUserPageTypes method, unable to delete user page types...");
                    return false;
                }   //if
                if (formParams == null)
                {
                    Logger.MyLogger.Log("UsersController exception: UpdateUserPageTypes method, form params null object...");
                    return false;
                }   //if
                String acceptablePageTypes = formParams.Get(UsersConsts.USER_PAGE_TYPES_REQUEST_PARAM);
                if (String.IsNullOrEmpty(acceptablePageTypes))
                {
                    return true;
                }   //if
                String[] acceptablePageTypeIds = acceptablePageTypes.Split(',');
                if (acceptablePageTypeIds == null)
                {
                    return true;
                }   //if
                foreach (string acceptablePageTypeId in acceptablePageTypeIds)
                {
                    UserPageType userPageType = new UserPageType();
                    userPageType.page_type_id = Int32.Parse(acceptablePageTypeId);
                    userPageType.user_id = user.user_id;
                    userPageType.user_page_type_created = DateTime.Now;
                    userPageType.user_page_type_modified = DateTime.Now;
                    if (this._userPageTypeDAO.Add(userPageType) == null)
                    {
                        Logger.MyLogger.Log("UsersController exception: UpdateUserPageTypes method, unable to add user language to database...");
                        return false;
                    }   //if null
                }   //foreach
                return true;
            }
            catch (Exception ex)
            {
                Logger.MyLogger.Log(ex);
                return false;
            }   //catch            
        }

        /// <summary>
        /// Metoda do aktualizacji uprawnien uzytkownika w bazie na podstawie zadania.
        /// </summary>
        /// <param name="user">uzytkownik z modelu danych z zadania</param>
        /// <returns>true, gdy sie uda, false wpp</returns>
        private bool UpdateUserGlobalPermissions(User userFromRequest, FormCollection formParams)
        {
            if (userFromRequest == null)
            {
                return false;
            }   //if null
            User userToUpdate = this._userDAO.FindByPK(userFromRequest.user_id);
            if (userToUpdate == null)
            {
                Logger.MyLogger.Log("UsersController exception: UpdateUserGlobalPermissions method, unable to find user to update...");
                return false;
            }   //if null
            userToUpdate.user_permission_access = (!String.IsNullOrEmpty(formParams.Get(UsersConsts.PERMISSION_ACCESS_REQUEST_PARAM)));
            return this._userDAO.SubmitChanges();
        }

        /// <summary>
        /// Metoda do sprawdzania czy ktos sobie nie wycial biezacej wersji jezykowej.
        /// </summary>
        /// <param name="userId">uzytkownik z modelu danych z zadania</param>
        /// <param name="currentLanguage">wersja jezykowa</param>
        /// <returns>true, gdy sie uda, false wpp</returns>
        private bool IsCurrentLanguageAvailable(int? userId, Language currentLanguage)
        {
            if (!userId.HasValue)
            {
                return false;
            }   //if null
            if (currentLanguage == null)
            {
                return false;
            }   //if null
            return (this._userLanguageDAO.FindByUserIdAndLanguageId(userId, currentLanguage.language_id) != null);
        }

        public ActionResult AccessDenied()
        {
            Language currentLanguage = this._languageDAO.GetDefaultLanguage(this.GetAuthenticatedUserId());
            if (currentLanguage != null)
            {
                return View("Errors/UsersErrorAccessDenied", this.GetBaseViewModel(currentLanguage.language_id));
            }   //if
            else
            {
                return View("Errors/UsersErrorAccessDenied", this.GetBaseViewModel(null));
            }   //else
        }

    }
}
